module CSR(
    input wire clk,
    input wire [13:0] csr_rnum,
    input wire [13:0] csr_rnum1,
    input wire [13:0] csr_rnum2,
    input wire [13:0] csr_wnum,
    input wire [31:0] wdata,
    input wire we,
    input wire we_h,
    input wire reset,
    output wire [31:0] rdata,
    output wire [31:0] rdata1,
    output wire [31:0] rdata2,
    output wire [12:0] int,
    output wire ie
    );

    reg[31:0]crmd;
    reg[31:0]prmd;
    reg[31:0]estat;
    reg[31:0]era;
    reg[31:0]eentry;
    reg[31:0]save0;
    reg[31:0]save1;
    reg[31:0]save2;
    reg[31:0]save3;
    reg[31:0]ecfg;
    reg[31:0]badv;
    reg[31:0]tid;
    reg[31:0]tcfg;
    reg[31:0]tval;
    reg[31:0]ticlr;

    reg[1:0]twe = 0;

    wire crmd_r  = csr_rnum == 14'h0000;
    wire prmd_r  = csr_rnum == 14'h0001;
    wire estat_r = csr_rnum == 14'h0005;
    wire era_r   = csr_rnum == 14'h0006;
    wire eentry_r= csr_rnum == 14'h000c;
    wire save0_r = csr_rnum == 14'h0030;
    wire save1_r = csr_rnum == 14'h0031;
    wire save2_r = csr_rnum == 14'h0032;
    wire save3_r = csr_rnum == 14'h0033;
    wire ecfg_r  = csr_rnum == 14'h0004;
    wire badv_r  = csr_rnum == 14'h0007;
    wire tid_r   = csr_rnum == 14'h0040;
    wire tcfg_r  = csr_rnum == 14'h0041;
    wire tval_r  = csr_rnum == 14'h0042;
    wire ticlr_r = csr_rnum == 14'h0044;

    wire crmd_r1  = csr_rnum1 == 14'h0000;
    wire prmd_r1  = csr_rnum1 == 14'h0001;
    wire estat_r1 = csr_rnum1 == 14'h0005;
    wire era_r1   = csr_rnum1 == 14'h0006;
    wire eentry_r1= csr_rnum1 == 14'h000c;
    wire save0_r1 = csr_rnum1 == 14'h0030;
    wire save1_r1 = csr_rnum1 == 14'h0031;
    wire save2_r1 = csr_rnum1 == 14'h0032;
    wire save3_r1 = csr_rnum1 == 14'h0033;
    wire ecfg_r1  = csr_rnum1 == 14'h0004;
    wire badv_r1  = csr_rnum1 == 14'h0007;
    wire tid_r1   = csr_rnum1 == 14'h0040;
    wire tcfg_r1  = csr_rnum1 == 14'h0041;
    wire tval_r1  = csr_rnum1 == 14'h0042;
    wire ticlr_r1 = csr_rnum1 == 14'h0044;

    wire crmd_r2  = csr_rnum2 == 14'h0000;
    wire prmd_r2  = csr_rnum2 == 14'h0001;
    wire estat_r2 = csr_rnum2 == 14'h0005;
    wire era_r2   = csr_rnum2 == 14'h0006;
    wire eentry_r2= csr_rnum2 == 14'h000c;
    wire save0_r2 = csr_rnum2 == 14'h0030;
    wire save1_r2 = csr_rnum2 == 14'h0031;
    wire save2_r2 = csr_rnum2 == 14'h0032;
    wire save3_r2 = csr_rnum2 == 14'h0033;
    wire ecfg_r2  = csr_rnum2 == 14'h0004;
    wire badv_r2  = csr_rnum2 == 14'h0007;
    wire tid_r2   = csr_rnum2 == 14'h0040;
    wire tcfg_r2  = csr_rnum2 == 14'h0041;
    wire tval_r2  = csr_rnum2 == 14'h0042;
    wire ticlr_r2 = csr_rnum2 == 14'h0044;

    wire crmd_w  = csr_wnum == 14'h0000;
    wire prmd_w  = csr_wnum == 14'h0001;
    wire estat_w = csr_wnum == 14'h0005;
    wire era_w   = csr_wnum == 14'h0006;
    wire eentry_w= csr_wnum == 14'h000c;
    wire save0_w = csr_wnum == 14'h0030;
    wire save1_w = csr_wnum == 14'h0031;
    wire save2_w = csr_wnum == 14'h0032;
    wire save3_w = csr_wnum == 14'h0033;
    wire ecfg_w  = csr_wnum == 14'h0004;
    wire badv_w  = csr_wnum == 14'h0007;
    wire tid_w   = csr_wnum == 14'h0040;
    wire tcfg_w  = csr_wnum == 14'h0041;
    wire tval_w  = csr_wnum == 14'h0042;
    wire ticlr_w = csr_wnum == 14'h0044;
    
    assign rdata  = crmd_r  ? {23'b0,crmd[8:0]} :
                    prmd_r  ? {29'b0,prmd[2:0]} :
                    estat_r ? {1'b0,estat[30:16],3'b0,estat[12:11],1'b0,estat[9:0]} :
                    era_r   ? era :
                    eentry_r? {eentry[31:6],6'b0} :
                    save0_r ? save0 :
                    save1_r ? save1 :
                    save2_r ? save2 :
                    save3_r ? save3 :
                    ecfg_r  ? {19'b0,ecfg[12:11],1'b0,ecfg[9:0]} :
                    badv_r  ? badv :
                    tid_r   ? tid :
                    tcfg_r  ? tcfg :
                    tval_r  ? tval :
                    ticlr_r ? 32'b0 : 32'b0;

    assign rdata1 = crmd_r1  ? {23'b0,crmd[8:0]} :
                    prmd_r1  ? {29'b0,prmd[2:0]} :
                    estat_r1 ? {1'b0,estat[30:16],3'b0,estat[12:11],1'b0,estat[9:0]} :
                    era_r1   ? era :
                    eentry_r1? {eentry[31:6],6'b0} :
                    save0_r1 ? save0 :
                    save1_r1 ? save1 :
                    save2_r1 ? save2 :
                    save3_r1 ? save3 :
                    ecfg_r1  ? {19'b0,ecfg[12:11],1'b0,ecfg[9:0]} :
                    badv_r1  ? badv :
                    tid_r1   ? tid :
                    tcfg_r1  ? tcfg :
                    tval_r1  ? tval :
                    ticlr_r1 ? 32'b0 : 32'b0;

    assign rdata2 = crmd_r2  ? {23'b0,crmd[8:0]} :
                    prmd_r2  ? {29'b0,prmd[2:0]} :
                    estat_r2 ? {1'b0,estat[30:16],3'b0,estat[12:11],1'b0,estat[9:0]} :
                    era_r2   ? era :
                    eentry_r2? {eentry[31:6],6'b0} :
                    save0_r2 ? save0 :
                    save1_r2 ? save1 :
                    save2_r2 ? save2 :
                    save3_r2 ? save3 :
                    ecfg_r2  ? {19'b0,ecfg[12:11],1'b0,ecfg[9:0]} :
                    badv_r2  ? badv :
                    tid_r2   ? tid :
                    tcfg_r2  ? tcfg :
                    tval_r2  ? tval :
                    ticlr_r2 ? 32'b0 : 32'b0;

    always@(negedge clk)begin
        if(tval == 0 && twe[0] == 1)begin
            estat[11] <= 1;
        end
        if(reset)begin
            crmd <= 32'h00000008;
            ecfg <= 32'b0;
            estat[12:0] <= 13'b0;
            tcfg[0] <= 0;
        end
        else if(we)begin
            if(crmd_w)begin
                crmd[8:0] <= wdata[8:0];
            end
            if(prmd_w)begin
                prmd[2:0] <= wdata[2:0];
            end
            if(estat_w)begin
                estat[1:0] <= wdata[1:0];
            end
            if(era_w)begin
                era <= wdata;
            end
            if(era_w)begin
                era <= wdata;
            end
            if(eentry_w)begin
                eentry[31:6] <= wdata[31:6];
            end
            if(save0_w)begin
                save0 <= wdata;
            end
            if(save1_w)begin
                save1 <= wdata;
            end
            if(save2_w)begin
                save2 <= wdata;
            end
            if(save3_w)begin
                save3 <= wdata;
            end
            if(ecfg_w)begin
                {ecfg[12:11],ecfg[9:0]} <= {wdata[12:11],wdata[9:0]};
            end
            if(badv_w)begin
                badv <= wdata;
            end
            if(tid_w)begin
                tid <= wdata;
            end
            if(tcfg_w)begin
                tcfg <= wdata;
            end
            if(ticlr_w)begin
                if(wdata[0] == 1)begin
                    estat[11] <= 0;
                end
            end
        end
        else if(we_h)begin
            if(crmd_w)begin
                crmd <= wdata;
            end
            if(prmd_w)begin
                prmd <= wdata;
            end
            if(estat_w)begin
                estat <= wdata;
            end
            if(era_w)begin
                era <= wdata;
            end
            if(era_w)begin
                era <= wdata;
            end
            if(eentry_w)begin
                eentry <= wdata;
            end
            if(save0_w)begin
                save0 <= wdata;
            end
            if(save1_w)begin
                save1 <= wdata;
            end
            if(save2_w)begin
                save2 <= wdata;
            end
            if(save3_w)begin
                save3 <= wdata;
            end
            if(ecfg_w)begin
                ecfg <= wdata;
            end
            if(badv_w)begin
                badv <= wdata;
            end
            if(tid_w)begin
                tid <= wdata;
            end
            if(tcfg_w)begin
                tcfg <= wdata;
            end
        end
    end

    //定时器
    always@(posedge clk)begin
        if(tcfg_w && we)begin
            tval <= {wdata[31:2],2'b00};
            twe <= wdata[1:0];
        end
        else if(twe[0] == 1)begin
            if(tval == 32'hffffffff)begin
                
            end
            else begin
                if(tval == 32'b0)begin
                    if(twe[1] == 1)begin
                        tval <= {tcfg[31:2],2'b00};
                    end
                    else tval <= tval - 1;
                end
                else begin
                    tval <= tval - 1;
                end
            end
        end
    end
    
    assign int    = estat[12:0] & ecfg[12:0];
    assign ie     = crmd[2];
endmodule
